package com.ophiux.wechat;

import org.springframework.util.StringUtils;

import java.io.*;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.*;

/**
 * 说明：自动生成MyBatis的实体类、实体映射XML文件、Mapper(暂时只适用mysql)<br>
 * <h1>创 建 人: hhl </h1>
 * 创建日期: 2019年1月29日 下午4:15:18<br>
 * 需要jar:mysql-connector-java,commons-lang3
 */
public class EntityUtil {
    /**
     * 数据库数据类型
     */
    private final static String type_char = "char";
    private final static String type_date = "date";
    private final static String type_timestamp = "timestamp";
    private final static String type_int = "int";
    private final static String type_bigint = "bigint";
    private final static String type_text = "text";
    private final static String type_bit = "bit";
    private final static String type_decimal = "decimal";
    private final static String type_blob = "blob";
    private final static String type_double = "double";

    /**
     * 文件生成位置配置
    */
	private final String path = "C:/Users/Admin/Desktop/xfstest/";
    /** 生成的entity文件存放路径 */
    private final String bean_path = path + "entity";
    /** 生成的mapper文件存放路径*/
    private final String mapper_path = path + "mapper";
    /** 生成的XML文件存放路径*/
    private final String xml_path = path + "xml";
    private final String service_path = path + "service";
    /** 实体类所属项目路径（根据自己做的项目相应调整）*/
    private static final String bean_package = "com.hnihealth.hncdm.travel.entity";
    /** Mapper类所属项目路径（根据自己做的项目相应调整）*/
    private final String mapper_package = "com.hnihealth.hncdm.travel.mapper";
    /** service*/
    private final String service_package = "com.hnihealth.hncdm.travel.service";
    
    /** 基础实现类所属项目路径*/
    private final String base_package = "com.baomidou.mybatisplus.core.mapper";
    private final String driverName = "com.mysql.cj.jdbc.Driver";
    /** 数据库用户名 */
	private final String user = "root";
	/** 数据库密码 */
	private final String password = "root";
	/** 数据库名称（根据自己模块做相应调整） */
	private final String moduleName = "tbcard";
	/** 数据库连接（根据自己模块做相应调整）*/
	private final String url = "jdbc:mysql://127.0.0.1:3306/" + moduleName + "?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true";
	/** 表名（需要生成的表）*/
	private static String tableName = "ophiux_app_user_answer";
    private static String beanName = null;
    private String mapperName = null;
    private Connection conn = null;
    /** 使用的持久层框架 M:MyBatis H:Hibernate */
    private String persistence_frame = "M";
    /** 是否序列化  Y:是  N:否 */
    private String serializable = "N";


    public static void main(String[] args) {
        try {
            System.out.println("=========开始生成=========");
//            new EntityUtil().generateAllTables();
            new EntityUtil().generate();
            System.out.println("=========生成结束=========");
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
    

    /**
     * 说明:初始化连接数据库 <br>
     * 创 建 人: hhl
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    private void init() throws ClassNotFoundException, SQLException {
        Class.forName(driverName);
        conn = DriverManager.getConnection(url, user, password);
    }
    
    public void generateAllTables() throws SQLException, ClassNotFoundException, IOException {
    	init();
        List<String> tableList = getTables();
        for (String table : tableList) {
        	tableName = table;
        	generate();
		}
    }
    
    public void generate() throws ClassNotFoundException, SQLException, IOException {
        System.out.println("==========生成中==========");
        init();
        //查询表所有的列信息
        String prefix = "show full fields from ";
        List<String> columns = null;
        List<String> types = null;
        List<String> comments = null;
        PreparedStatement pstate;
        columns = new ArrayList<String>();
        types = new ArrayList<String>();
        comments = new ArrayList<String>();
        pstate = conn.prepareStatement(prefix + tableName);
        ResultSet results = pstate.executeQuery();
        while (results.next()) {
        	//字段名
            columns.add(results.getString("FIELD"));
            //字段类型
            types.add(results.getString("TYPE"));
            //字段注释
            comments.add(results.getString("COMMENT"));
        }
        
        //查询表信息
        String prefix2 = "show table status where name='"+tableName+"'";
        PreparedStatement  pstate2 = conn.prepareStatement(prefix2);
        ResultSet results2 = pstate2.executeQuery();
        //表注释
        String tableComment = "";
        while(results2.next()) {
        	tableComment = results2.getString("COMMENT");
        }
        
        processTable(tableName);
        
        //TODO 生成
        //生成实体
        buildEntityBean(columns, types, comments, tableName,tableComment);
        //生成dto
        buildEntityBeanDTO(columns, types, comments, tableName,tableComment);
        buildQueryModel(columns, types, comments, tableName,tableComment);
        buildInertModel(columns, types, comments, tableName, tableComment);
        buildUpdateModel(columns, types, comments, tableName, tableComment);
        
        //生成service
        buildService(tableName, tableComment);
        //生成serviceImpl
        buildServiceImpl(tableName, tableComment);
        
        //使用MyBatis才生成Mapper文件
        if (persistence_frame.equals("M")) {
            buildMapper(types,tableName,tableComment);
//            buildMapperXml(columns, types, comments);
        }
        conn.close();
    }
    
    
    /**
     * 说明: 获取所有的数据库表注释<br>
     * 创 建 人: hhl
     * @return
     * @throws SQLException
     */
    @SuppressWarnings("unused")
	private Map<String, String> getTableComment() throws SQLException {
        Map<String, String> maps = new HashMap<String, String>();
        PreparedStatement pstate = conn.prepareStatement("show table status");
        ResultSet results = pstate.executeQuery();
        while (results.next()) {
            String tableName = results.getString("NAME");
            String comment = results.getString("COMMENT");
            maps.put(tableName, comment);
        }
        return maps;
    }
    

    /**
     * 说明: 获取所有的表<br>
     * 创 建 人: hhl
     * @return	List表集合
     * @throws SQLException
     */
	private List<String> getTables() throws SQLException {
        List<String> tables = new ArrayList<String>();
        PreparedStatement pstate = conn.prepareStatement("show tables");
        ResultSet results = pstate.executeQuery();
        while (results.next()) {
        	String tableName = results.getString(1);
        	tables.add(tableName);
        }
        return tables;
    }


    /**
     * 说明: 生成Mapper文件名<br>
     * 创 建 人: hhl
     * @param table 表名
     */
    private void processTable(String table) {
        StringBuilder sb = new StringBuilder(table.length());
        String tableNew = table.toLowerCase();
        String[] tables = tableNew.split("_");
        String temp;
        for (String table1 : tables) {
            temp = table1.trim();
            sb.append(temp.substring(0, 1).toUpperCase()).append(temp.substring(1));
        }
        beanName = sb.toString();
        mapperName = beanName + "Mapper";
    }


    /**
     * 数据库数据类型与Java数据类型转换
     */
    private static String processType(String type) {
    	//万能字符串
//    	if("1".equals("1")) {
//    		return "String";
//    	}
        if (type.contains(type_char)) {
            return "String";
        } else if (type.contains(type_bigint)) {
            return "Long";
        } else if (type.contains(type_int)) {
            if (type.startsWith(type_int) && type.contains("unsigned")) {
                return "Long";
            } else {
                return "Integer";
            }
        } else if (type.contains(type_date)) {
            return "LocalDateTime";
        } else if (type.contains(type_text)) {
            return "String";
        } else if (type.contains(type_timestamp)) {
            return "LocalDateTime";
        } else if (type.contains(type_bit)) {
            return "Boolean";
        } else if (type.contains(type_decimal)) {
            return "BigDecimal";
        } else if (type.contains(type_blob)) {
            return "byte[]";
        } else if (type.contains(type_double)) {
            return "Double";
        }
        return type;
    }


    private static String processField(String field) {
        StringBuffer sb = new StringBuffer();
        //_后的首字母是否大写
        field = field.toLowerCase();
        String[] fields = field.split("_");
        String temp;
        sb.append(fields[0]);
        for (int i = 1; i < fields.length; i++) {
            temp = fields[i].trim();
            sb.append(temp.substring(0, 1).toUpperCase()).append(temp.substring(1));
        }
        return sb.toString();
//        return field;
    }


    /**
     * 将实体类名首字母改为小写
     */
    private static String processResultMapId(String beanName) {
        return beanName.substring(0, 1).toLowerCase() + beanName.substring(1);
    }

    /**
     * 说明: 构建类上面的注释<br>
     * 创 建 人: hhl
     * @param bw
     * @param tableComment		表注释
     * @return
     * @throws IOException
     */
    private BufferedWriter buildClassComment(BufferedWriter bw, String tableComment) throws IOException {
        bw.newLine();
        bw.newLine();
        bw.write("/**");
        //bw.newLine();
        //bw.write(" * ");
        bw.newLine();
        bw.write(" * @desc:" + tableComment);
        bw.newLine();
        bw.write(" * @autor: hhl ");
        bw.newLine();
        bw.write(" * @date: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"<br>");
        bw.newLine();
        bw.write(" */");
        return bw;
    }


    /**
     * 说明: 构建方法上面的注释<br>
     * 创 建 人: hhl
     * @param bw
     * @param text	注释
     * @return
     * @throws IOException
     */
    private BufferedWriter buildMethodComment(BufferedWriter bw, String text) throws IOException {
        bw.newLine();
        bw.write("\t/**");
        bw.newLine();
        bw.write("\t * " + text);
        bw.newLine();
        bw.write("\t */");
        return bw;
    }

    /**
     * 说明: 构建属性（字段）上面的注释<br>
     * 创 建 人: hhl
     * @param bw
     * @param text 注释
     * @return
     * @throws IOException
     */
    private BufferedWriter buildFieldComment(BufferedWriter bw, String text) throws IOException {
        bw.newLine();
        if (null != text && !text.trim().equals("")) {
            bw.write("\t/**");
            bw.newLine();
            bw.write("\t * " + text);
            bw.newLine();
            bw.write("\t */");
        }
        return bw;
    }

    /**
     * 说明: 生成实体类<br>
     * 创 建 人: hhl
     * @param columns	字段名集合
     * @param types		字段类型集合
     * @param comments	字段注释
     * @param tableName		表名
     * @param tableComment	表注释
     * @throws IOException
     */
    private void buildEntityBean(List<String> columns, List<String> types, List<String> comments, String tableName, String tableComment)
            throws IOException {
        File folder = new File(bean_path);
        if (!folder.exists()) {
            folder.mkdirs();
        }

        File beanFile = new File(bean_path, beanName + ".java");
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(beanFile)));
        bw.write("package " + bean_package + ";");
        bw.newLine();

        //region 包引入
        bw.newLine();
        if("Y".equals(serializable)) {
        	bw.write("import java.io.Serializable;");
        }
        if (persistence_frame.equals("M")) {
//            bw.newLine();
//            bw.write("import lombok.AllArgsConstructor;");
//            bw.newLine();
//            bw.write("import lombok.Builder;");
//        	bw.newLine();
            bw.write("import lombok.Data;");
            bw.newLine();
//            bw.write("import lombok.NoArgsConstructor;");
            bw.write("import com.baomidou.mybatisplus.annotation.TableName;");
            bw.newLine();
            bw.write("import lombok.EqualsAndHashCode;");
            bw.newLine();
            bw.write("import lombok.experimental.Accessors;");
            bw.newLine();
            bw.write("import com.baomidou.mybatisplus.extension.activerecord.Model;");
            bw.newLine();

        }
        if (persistence_frame.equals("H")) {
            bw.newLine();
            bw.write("import javax.persistence.*;");
        }
        //endregion

        //region 类注释
        bw = buildClassComment(bw, tableComment);
        bw.write("");
        //endregion

        //region 是否添加注解
        if (persistence_frame.equals("M")) {
            bw.newLine();
            bw.write("@Data");
            bw.newLine();
            bw.write("@EqualsAndHashCode(callSuper = true)");
            bw.newLine();
            bw.write("@Accessors(chain = true)");
            bw.newLine();
            bw.write("@TableName(\"" + tableName + "\")");
            
//            bw.newLine();
//            bw.write("@Getter");
//            bw.newLine();
//            bw.write("@Setter");
//            bw.newLine();
//            bw.write("@Builder");
//            bw.newLine();
//            bw.write("@NoArgsConstructor");
//            bw.newLine();
//            bw.write("@AllArgsConstructor");
        }
        if (persistence_frame.equals("H")) {
            bw.newLine();
            bw.write("@Entity");
            bw.newLine();
            bw.write("@Table(name = \"" + tableName + "\")");
        }
        //endregion

        bw.newLine();
        if("Y".equals(serializable)) {
        	bw.write("public class " + beanName + " implements Serializable" + " {");
        }else {
            bw.write("public class " + beanName + " extends Model<"+beanName+"> {");
        }
        
        bw.newLine();
        int size = columns.size();
        for (int i = 0; i < size; i++) {
            if("id".equals(columns.get(i))){
                bw.newLine();
                bw.write("\t@TableId(type = IdType.AUTO)");
            }
            if("created_by".equals(columns.get(i))){
                bw.newLine();
                bw.write("\t@TableField(value = \"created_by\", fill = FieldFill.INSERT)");
            }
            if("created_time".equals(columns.get(i))){
                bw.newLine();
                bw.write("\t@TableField(value = \"created_time\", fill = FieldFill.INSERT)");
            }
            if("updated_by".equals(columns.get(i))){
                bw.newLine();
                bw.write("\t@TableField(value = \"updated_by\", fill = FieldFill.UPDATE)");
            }
            if("updated_time".equals(columns.get(i))){
                bw.newLine();
                bw.write("\t@TableField(value = \"updated_time\", fill = FieldFill.UPDATE)");
            }
            bw.newLine();
            bw.write("\t@ApiModelProperty(value = \""+comments.get(i)+"\")");
//            buildFieldComment(bw, comments.get(i));
            bw.newLine();
            bw.write("\tprivate " + processType(types.get(i)) + " " + processField(columns.get(i)) + ";");
            bw.newLine();
            bw.write("");
        }

        bw.newLine();
        bw.write("}");
        bw.newLine();
        bw.flush();
        bw.close();
    }

    /**
     * 说明: 生成返回DTO<br>
     * 创 建 人: hhl
     * @param columns	字段名集合
     * @param types		字段类型集合
     * @param comments	字段注释
     * @param tableName		表名
     * @param tableComment	表注释
     * @throws IOException
     */
    private void buildEntityBeanDTO(List<String> columns, List<String> types, List<String> comments, String tableName, String tableComment)
            throws IOException {
        File folder = new File(bean_path+"/dto");
        if (!folder.exists()) {
            folder.mkdirs();
        }

        File beanFile = new File(bean_path+"/dto", beanName + "DTO.java");
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(beanFile)));
        bw.write("package " + bean_package + ";");
        bw.newLine();

        //region 包引入
        bw.newLine();
        if("Y".equals(serializable)) {
        	bw.write("import java.io.Serializable;");
        }
        if (persistence_frame.equals("M")) {
//            bw.newLine();
//            bw.write("import lombok.AllArgsConstructor;");
//            bw.newLine();
//            bw.write("import lombok.Builder;");
//        	bw.newLine();
            bw.write("import lombok.Data;");
            bw.newLine();
            bw.write("import io.swagger.annotations.ApiModel;");
            bw.newLine();
            bw.write("import io.swagger.annotations.ApiModelProperty;");
            bw.newLine();
//            bw.write("import lombok.NoArgsConstructor;");
        }

        bw.newLine();
        bw.write("@Data");
        bw.newLine();
        bw.write("@ApiModel(\""+tableComment+"  --  返回实体\")");

        bw.newLine();
        if("Y".equals(serializable)) {
        	bw.write("public class " + beanName + " implements Serializable" + " {");
        }else {
        	bw.write("public class " + beanName+"DTO" + " {");
        }
        bw.newLine();
        int size = columns.size();
        for (int i = 0; i < size; i++) {
            bw.newLine();
            bw.write("\t@ApiModelProperty(value = \""+comments.get(i)+"\")");
            bw.newLine();
            bw.write("\tprivate " + processType(types.get(i)) + " " + processField(columns.get(i)) + ";");
            bw.newLine();
            bw.write("");
        }

        bw.newLine();
        bw.write("}");
        bw.newLine();
        bw.flush();
        bw.close();
    }
    
    /**
     * 生成查询参数
     * @param columns
     * @param types
     * @param comments
     * @param tableName
     * @param tableComment
     * @throws IOException
     */
	private void buildQueryModel(List<String> columns, List<String> types, List<String> comments, String tableName, String tableComment) throws IOException {
        File folder = new File(bean_path+"/query");
        if (!folder.exists()) {
            folder.mkdirs();
        }

        File beanFile = new File(bean_path+"/query", beanName + "QueryModel.java");
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(beanFile)));
        bw.write("package " + bean_package + ".query;");
        bw.newLine();

        if("Y".equals(serializable)) {
        	bw.newLine();
        	bw.write("import java.io.Serializable;");
        }
        
        if (persistence_frame.equals("M")) {
        	bw.newLine();
            bw.write("import lombok.Data;");
            bw.newLine();
            bw.write("import io.swagger.annotations.ApiModel;");
            bw.newLine();
            bw.write("import io.swagger.annotations.ApiModelProperty;");
            bw.newLine();
        }

        bw.newLine();
        bw.write("@Data");
        bw.newLine();
        bw.write("@ApiModel(\""+tableComment+"  --  查询参数\")");

        bw.newLine();
        if("Y".equals(serializable)) {
        	bw.write("public class " + beanName + " implements Serializable" + " {");
        }else {
        	bw.write("public class " + beanName+"QueryModel" + " {");
        }

        bw.newLine();
        bw.write("}");
        bw.newLine();
        bw.flush();
        bw.close();
    }
	
	/**
	 * 生成新增参数
	 * @param columns
	 * @param types
	 * @param comments
	 * @param tableName
	 * @param tableComment
	 * @throws IOException
	 */
	private void buildInertModel(List<String> columns, List<String> types, List<String> comments, String tableName, String tableComment) throws IOException {
        File folder = new File(bean_path+"/insert");
        if (!folder.exists()) {
            folder.mkdirs();
        }

        File beanFile = new File(bean_path+"/insert", beanName + "InsertModel.java");
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(beanFile)));
        bw.write("package " + bean_package + ".insert;");
        bw.newLine();

        if("Y".equals(serializable)) {
        	bw.newLine();
        	bw.write("import java.io.Serializable;");
        }
        
        if (persistence_frame.equals("M")) {
        	bw.newLine();
            bw.write("import lombok.Data;");
            bw.newLine();
            bw.write("import io.swagger.annotations.ApiModel;");
            bw.newLine();
            bw.write("import io.swagger.annotations.ApiModelProperty;");
            bw.newLine();
        }

        bw.newLine();
        bw.write("@Data");
        bw.newLine();
        bw.write("@ApiModel(\""+tableComment+"  --  新增参数\")");

        bw.newLine();
        if("Y".equals(serializable)) {
        	bw.write("public class " + beanName + " implements Serializable" + " {");
        }else {
        	bw.write("public class " + beanName+"InsertModel" + " {");
        }
        
        bw.newLine();
        int size = columns.size();
        for (int i = 0; i < size; i++) {
        	if(columns.get(i).equals("id") || columns.get(i).equals("created_at")|| columns.get(i).equals("updated_at")) {
        		continue;
        	}
            bw.newLine();
        	bw.write("\t@ApiModelProperty(value=\""+comments.get(i)+"\")");
            bw.newLine();
            bw.write("\tprivate " + processType(types.get(i)) + " " + processField(columns.get(i)) + ";");
            bw.newLine();
        }

        bw.newLine();
        bw.write("}");
        bw.newLine();
        bw.flush();
        bw.close();
    }
	
	/**
	 * 生成修改参数
	 * @param columns
	 * @param types
	 * @param comments
	 * @param tableName
	 * @param tableComment
	 * @throws IOException
	 */
	private void buildUpdateModel(List<String> columns, List<String> types, List<String> comments, String tableName, String tableComment) throws IOException {
        File folder = new File(bean_path+"/update");
        if (!folder.exists()) {
            folder.mkdirs();
        }

        File beanFile = new File(bean_path+"/update", beanName + "UpdateModel.java");
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(beanFile)));
        bw.write("package " + bean_package + ".update;");
        bw.newLine();

        if("Y".equals(serializable)) {
        	bw.newLine();
        	bw.write("import java.io.Serializable;");
        }
        
        if (persistence_frame.equals("M")) {
        	bw.newLine();
            bw.write("import lombok.Data;");
            bw.newLine();
            bw.write("import io.swagger.annotations.ApiModel;");
            bw.newLine();
            bw.write("import io.swagger.annotations.ApiModelProperty;");
            bw.newLine();
        }

        bw.newLine();
        bw.write("@Data");
        bw.newLine();
        bw.write("@ApiModel(\""+tableComment+"  --  修改参数\")");

        bw.newLine();
        if("Y".equals(serializable)) {
        	bw.write("public class " + beanName + " implements Serializable" + " {");
        }else {
        	bw.write("public class " + beanName+"UpdateModel" + " {");
        }
        
        bw.newLine();
        int size = columns.size();
        for (int i = 0; i < size; i++) {
        	if(columns.get(i).equals("created_at")|| columns.get(i).equals("updated_at")) {
        		continue;
        	}
            bw.newLine();
        	bw.write("\t@ApiModelProperty(value=\""+comments.get(i)+"\")");
            bw.newLine();
            bw.write("\tprivate " + processType(types.get(i)) + " " + processField(columns.get(i)) + ";");
            bw.newLine();
        }

        bw.newLine();
        bw.write("}");
        bw.newLine();
        bw.flush();
        bw.close();
    }


    /**
     * 说明: 构建Mapper文件<br>
     * 创 建 人: hhl
     * @param types	字段类型集合
     * @param tableName 	表名
     * @param tableComment 	表注释
     * @throws IOException
     */
    private void buildMapper(List<String> types,String tableName,String tableComment) throws IOException {
        File folder = new File(mapper_path);
        if (!folder.exists()) {
            folder.mkdirs();
        }

        File mapperFile = new File(mapper_path, mapperName + ".java");
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(mapperFile), "utf-8"));
        bw.write("package " + mapper_package + ";");
        bw.newLine();
        bw.newLine();
        bw.write("import java.util.List;");

        if (!StringUtils.isEmpty(base_package)) {
            bw.newLine();
            bw.write("import " + base_package + "." + "BaseMapper;");
            bw.newLine();
            bw.write("import " + bean_package + "." + beanName + ";");
        } else {
            bw.write("import " + bean_package + "." + beanName + ";");
        }

        bw = buildClassComment(bw, tableComment + mapperName);

        if (!StringUtils.isEmpty(base_package)) {
            bw.newLine();
            bw.write("public interface " + mapperName + " extends BaseMapper<" + beanName + "> " + "{");
        } else {
            bw.newLine();
            bw.write("public interface " + mapperName + "{");
        }
        
//        bw.newLine();
//        bw.newLine();
//        bw.write("\t/**");
//        bw.newLine();
//        bw.write("\t * 检测是否存在");
//        bw.newLine();
//        bw.write("\t */");
//        bw.newLine();
//        bw.write("\t//@Select(\"select * from "+tableName+" where name=#{name}\")");
//        bw.newLine();
//        bw.write("\t"+beanName+" checkUnique(@Param(\"name\")String name);");
        
        
        bw.newLine();
        bw.newLine();
        bw.write("}");
        bw.flush();
        bw.close();
    }


    /**
     * 说明: 构建实体类映射XML文件<br>
     * 创 建 人: hhl
     * @param columns	字段名集合
     * @param types		字段类型集合
     * @param comments	字段注释
     * @throws IOException
     */
    private void buildMapperXml(List<String> columns, List<String> types, List<String> comments) throws IOException {
        File folder = new File(xml_path);
        if (!folder.exists()) {
            folder.mkdirs();
        }

        String xmlMapper = beanName + "Mapper";
        File mapperXmlFile = new File(xml_path, xmlMapper + ".xml");
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(mapperXmlFile)));
        bw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        bw.newLine();
        bw.write("<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" ");
        bw.newLine();
        bw.write("    \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">");
        bw.newLine();
        bw.write("<mapper namespace=\"" + mapper_package + "." + mapperName + "\">");
        bw.newLine();
        bw.newLine();

        bw.write("\t<!--实体映射-->");
        bw.newLine();
        bw.write("\t<resultMap id=\"" + this.processResultMapId(beanName) + "ResultMap\" type=\"" + bean_package + "." + beanName + "\">");
        bw.newLine();
        bw.write("\t\t<!--" + comments.get(0) + "-->");
        bw.newLine();
        bw.write("\t\t<id property=\"" + this.processField(columns.get(0)) + "\" column=\"" + columns.get(0) + "\" />");
        bw.newLine();
        int size = columns.size();
        for (int i = 1; i < size; i++) {
            bw.write("\t\t<!--" + comments.get(i) + "-->");
            bw.newLine();
            bw.write("\t\t<result property=\""
                    + this.processField(columns.get(i)) + "\" column=\"" + columns.get(i) + "\" />");
            bw.newLine();
        }
        bw.write("\t</resultMap>");

        bw.newLine();
        bw.newLine();
        bw.newLine();

        // 下面开始写SqlMapper中的方法
        buildSQL(bw, columns, types);

        bw.write("</mapper>");
        bw.flush();
        bw.close();
    }

    /**
     * 说明: 构建增、删、改、查sql语句<br>
     * 创 建 人: hhl
     * @param bw
     * @param columns	字段名集合
     * @param types		字段类型集合
     * @throws IOException
     */
    private void buildSQL(BufferedWriter bw, List<String> columns, List<String> types) throws IOException {
        
    	//创建通用列字段名
    	BaseColumnList(bw, columns, types);
        
        // 通用结果条件
    	ParamSQL(bw, columns, types);

        // 查询（根据主键ID查询）
    	selectByPrimaryKey(bw, columns, types);
        

        // 查询（根据条件查询列表）
    	selectListByParam(bw, columns, types);
    	

        // 删除（根据主键ID删除）
    	deleteByPrimaryKey(bw, columns, types);


        //新增（匹配有值的字段）
        insert(bw, columns, types);

        // 修改update方法
        update(bw, columns, types);

        bw.newLine();
    }


    /**
     * 说明: 创建sql通用列<br>
     * 创 建 人: hhl
     * @param bw
     * @param columns
     * @param types
     * @throws IOException 
     */
    public static void BaseColumnList(BufferedWriter bw, List<String> columns, List<String> types) throws IOException {
        int size = columns.size();
    	 // 通用结果列
        bw.write("\t<!-- 通用查询结果列-->");
        bw.newLine();
        bw.write("\t<sql id=\"Base_Column_List\">");
        bw.newLine();

        for (int i = 0; i < size; i++) {
            bw.write("\t\t");
            bw.write(columns.get(i));
            if (i != size - 1) {
                bw.write(",");
                bw.newLine();
            }
        }

        bw.newLine();
        bw.write("\t</sql>");
        bw.newLine();
        bw.newLine();
    }
    
    /**
     * 说明:通用查询条件 <br>
     * 创 建 人: hhl
     * @param bw
     * @param columns
     * @param types
     * @throws IOException
     */
    public static void ParamSQL(BufferedWriter bw, List<String> columns, List<String> types) throws IOException{
	    bw.write("\t<!-- 通用查询条件-->");
	    bw.newLine();
	    bw.write("\t<sql id=\"ParamSQL\">");
	    bw.newLine();
	
	    for (int k = 1; k < columns.size(); k++) {
	        String tempField = processField(columns.get(k));
	        bw.write("\t\t <if test=\"" + tempField + " != null and "+tempField+" !='' \">");
	        bw.newLine();
	        bw.write("\t\t\t AND " + columns.get(k) + " = #{" + tempField + "}");
	        bw.newLine();
	        bw.write("\t\t </if>");
	        bw.newLine();
	    }
	
	    bw.write("\t</sql>");
	    bw.newLine();
	    bw.newLine();
    }
    
    /**
     * 说明: 查询（根据主键ID查询）<br>
     * 创 建 人: hhl
     * @param bw
     * @param columns
     * @param types
     * @throws IOException
     */
    public static void selectByPrimaryKey(BufferedWriter bw, List<String> columns, List<String> types) throws IOException{
    	bw.write("\t<!-- 查询（根据主键ID查询） -->");
        bw.newLine();
        bw.write("\t<select id=\"selectByPrimaryKey\" parameterType=\"java.lang." + processType(types.get(0)) + "\" resultMap=\"" + processResultMapId(beanName) + "ResultMap\" >");
        bw.newLine();
        bw.write("\t\t SELECT");
        bw.newLine();
        bw.write("\t\t\t <include refid=\"Base_Column_List\" />");
        bw.newLine();
        bw.write("\t\t FROM " + tableName);
        bw.newLine();
        bw.write("\t\t WHERE " + columns.get(0) + " = #{" + processField(columns.get(0)) + "}");
        bw.newLine();
        bw.write("\t</select>");
        bw.newLine();
        bw.newLine();
    }
    
    /**
     * 说明: 查询（根据条件查询列表）<br>
     * 创 建 人: hhl
     * @param bw
     * @param columns
     * @param types
     * @throws IOException
     */
    public static void selectListByParam(BufferedWriter bw, List<String> columns, List<String> types) throws IOException{
    	 bw.write("\t<!-- 查询（根据条件查询列表） -->");
         bw.newLine();
         bw.write("\t<select id=\"selectListByParam\" parameterType=\"" + bean_package + "." + beanName + "\" resultMap=\"" + processResultMapId(beanName) + "ResultMap\">");
         bw.newLine();
         bw.write("\t\t SELECT");
         bw.newLine();
         bw.write("\t\t\t <include refid=\"Base_Column_List\" />");
         bw.newLine();
         bw.write("\t\t FROM " + tableName);
         bw.newLine();
         bw.write("\t\t <where>");
         bw.newLine();
         bw.write("\t\t\t <include refid=\"ParamSQL\" />");
         bw.newLine();
         bw.write("\t\t</where>");
         bw.newLine();
         bw.write("\t</select>");
         bw.newLine();
         bw.newLine();
    }
    
    /**
     * 说明: 删除：根据主键ID删除<br>
     * 创 建 人: hhl
     * @param bw
     * @param columns
     * @param types
     * @throws IOException
     */
    public static void deleteByPrimaryKey(BufferedWriter bw, List<String> columns, List<String> types) throws IOException{
    	 bw.write("\t<!--删除：根据主键ID删除-->");
         bw.newLine();
         bw.write("\t<delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang." + processType(types.get(0)) + "\">");
         bw.newLine();
         bw.write("\t\t DELETE FROM " + tableName);
         bw.newLine();
         bw.write("\t\t WHERE " + columns.get(0) + " = #{" + processField(columns.get(0)) + "}");
         bw.newLine();
         bw.write("\t</delete>");
         bw.newLine();
         bw.newLine();
    }
    
    /**
     * Description: 新增 <br>
     * 创 建 人: hhl
     * 创建日期:2019年2月15日 下午2:20:18
     * @param bw
     * @param columns
     * @param types
     * @throws IOException
     */
    public static void insert(BufferedWriter bw, List<String> columns, List<String> types) throws IOException{
    	 bw.write("\t<!-- 添加 （匹配有值的字段）-->");
         bw.newLine();
         bw.write("\t<insert id=\"insert\" parameterType=\"" + bean_package + "." + beanName + "\">");
         bw.newLine();
         bw.write("\t\t INSERT INTO " + tableName);
         bw.newLine();
         bw.write("\t\t <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\" >");
         bw.newLine();

         String tempField;
         for (String column : columns) {
             tempField = processField(column);
             bw.write("\t\t\t<if test=\"" + tempField + " != null and "+tempField+" !='' \">");
             bw.write(column + ",");
             bw.write("</if>");
             bw.newLine();
         }

         bw.write("\t\t </trim>");
         bw.newLine();

         bw.write("\t\t <trim prefix=\"values (\" suffix=\")\" suffixOverrides=\",\" >");
         bw.newLine();

         for (String column : columns) {
             tempField = processField(column);
             bw.write("\t\t\t<if test=\"" + tempField + " != null and "+tempField+" !='' \">");
             bw.write(" #{" + tempField + "},");
             bw.write("</if>");
             bw.newLine();
         }

         bw.write("\t\t </trim>");
         bw.newLine();
         bw.write("\t</insert>");
         bw.newLine();
         bw.newLine();
    }
    
    /**
     * Description: 修改<br>
     * 创 建 人: hhl
     * 创建日期:2019年2月15日 下午2:23:17
     * @param bw
     * @param columns
     * @param types
     * @throws IOException
     */
    public static void update(BufferedWriter bw, List<String> columns, List<String> types) throws IOException{
    	bw.write("\t<!-- 修 改-->");
        bw.newLine();
        bw.write("\t<update id=\"update\" parameterType=\"" + bean_package + "." + beanName + "\">");
        bw.newLine();
        bw.write("\t\t UPDATE " + tableName);
        bw.newLine();
        bw.write("\t\t <trim prefix=\"set\" suffixOverrides=\",\">");
        bw.newLine();

        String tempField;
        for (int i = 1; i < columns.size(); i++) {
            tempField = processField(columns.get(i));
            bw.write("\t\t\t<if test=\"" + tempField + " != null and "+tempField+" !='' \">");
            bw.write(columns.get(i) + " = #{" + tempField + "},");
            bw.write("</if>");
            bw.newLine();
        }

        bw.write("\t\t</trim>");
        bw.newLine();
        bw.write("\t\t WHERE " + columns.get(0) + " = #{" + processField(columns.get(0)) + "}");
        bw.newLine();
        bw.write("\t</update>");
        bw.newLine();
        bw.newLine();
    }
    
    
    
    /**
     * 生成service
     * @param tableName		表名
     * @param tableComment	表注释
     * @throws IOException
     */
	private void buildService(String tableName, String tableComment) throws IOException {
		File folder = new File(service_path);
		if (!folder.exists()) {
			folder.mkdirs();
		}
		File file = new File(service_path, beanName + "Service.java");
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
		bw.write("package " + service_package + ";");
		bw.newLine();
		bw.write("import java.util.List;");
		bw.newLine();
		bw.write("import com.baomidou.mybatisplus.core.metadata.IPage;");
		bw.newLine();
		bw.write("import com.baomidou.mybatisplus.extension.service.IService;");
		
		buildClassComment(bw, tableComment+"接口层");
        bw.newLine();
		bw.write("public interface " + beanName + "Service extends IService<" + beanName + "> {");
		bw.newLine();


        bw.write("}");
        bw.newLine();
        bw.flush();
        bw.close();
	}
	
	/**
	 * 生成serviceImpl
	 * @param tableName		表名
	 * @param tableComment	表注释
	 * @throws IOException
	 */
	private void buildServiceImpl(String tableName, String tableComment) throws IOException {
		File folder = new File(service_path+"/impl");
		if (!folder.exists()) {
			folder.mkdirs();
		}
		File file = new File(service_path+"/impl", beanName + "ServiceImpl.java");
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
		bw.write("package " + service_package + ".impl;");
		bw.newLine();
		bw.write("import java.util.List;");
		bw.newLine();
		bw.write("import org.modelmapper.ModelMapper;");
		bw.newLine();
		bw.write("import org.springframework.beans.BeanUtils;");
		bw.newLine();
		bw.write("import org.springframework.beans.factory.annotation.Autowired;");
		bw.newLine();
		bw.write("import org.springframework.stereotype.Service;");
		bw.newLine();
		bw.write("import org.springframework.util.ObjectUtils;");
		bw.newLine();
		bw.write("import org.springframework.util.StringUtils;");
		bw.newLine();
		bw.write("import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;");
		bw.newLine();
		bw.write("import com.baomidou.mybatisplus.core.metadata.Page;");
		bw.newLine();
		bw.write("import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;");
		bw.newLine();
		bw.write("import org.modelmapper.TypeToken;");
		
		buildClassComment(bw, tableComment+"接口实现层");
        bw.newLine();
        bw.write("@Service");
        bw.newLine();
        bw.write("public class " + beanName + "ServiceImpl extends ServiceImpl<"+beanName+"Mapper,"+beanName+"> implements "+beanName+"Service {");
		bw.newLine();
		bw.newLine();
		

        bw.write("}");
        bw.newLine();
        bw.flush();
        bw.close();
	}

}